package Array.TwoIndex;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 15 三数之和
 * 给你一个整数数组 nums ，判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ，同时还满足 nums[i] + nums[j] + nums[k] == 0 。
 * 思路：
 *  分析这道题， 需要三个指针进行下表判断，才能满足 i+j+k == 0 , 但是可以简化，用一个循环固定一个指针，只剩下两个，满足 i+j+K == 0 就能加入数组，但是要注意去重，不能返回重复的
 *  解题：
 *  1： 定义一个循环，固定i下表， i的区间是 0 <i < num.length-2， i要去重， if(i>0 && inum==i-1num) continue;
 *  2: 在循环中，定义两个指针j、k，分别代表左右边界， j = i+1, k =nums.length-1 , 需要注意去重
 *  3:  判断条件， while(j<k)  , sum = nums[i] + nums[j] + nums[k]
 *  if(sum == 0) 加入数组，然后去重 不能添加重复的j与k， j++,k--;
    if(sum < 0) 证明当前最小值j小了，左边界要移动，j++
    if(sum > 0) 证明当前最大值k大了，右边界要移动，k--
    4: 返回结果
 */
public class ThreeSum {
    public List<List<Integer>> threeSum(int[] nums) {
        // 编辑条件，数组大小小于3直接返回为空
        if (nums == null || nums.length < 3){
            return null;
        }
        // 数组要进行排序
        Arrays.sort(nums);
        // 结果数组
        List<List<Integer>> res = new ArrayList<>();
        // 固定第一位
        for (int i = 0; i < nums.length-2 ; i++) {
            // 如果首位最小的数都大于0，那么肯定没有最小的数，直接返回
            if(nums[i] >0){
                return res;
            }
            // i去重
            if(i>0 && nums[i] == nums[i-1]){
                continue;
            }
            // 循环内定义j，k变量
            int j = i+1;
            int k = nums.length-1;
            while (j < k){
                int sum = nums[i] + nums[j] + nums[k];
                if(sum == 0){
                    List<Integer> temp = new ArrayList<>();
                    temp.add(nums[i]);
                    temp.add(nums[j]);
                    temp.add(nums[k]);
                    res.add(temp);
                    // 这里要去重，防止重复的j与k
                    while (j<k && nums[j+1] == nums[j]){
                        j++;
                    }
                    while (j<k && nums[k-1] == nums[k]){
                        k--;
                    }
                    //指针改变
                    j++;
                    k--;
                }else if(sum <0){ //最小值要增大
                    j++;
                }else {
                    k--;
                }
            }
        }
        return res;
    }
}
